Перейти к основному содержимому

5.01. Переменные

Разработчику Архитектору

Переменные

Hoisting
Область действия (функциональная, блочная)
Глобальное пространство имён
using, await using (современное управление ресурсами)

Для своей работы, функции используют какие-то данные. Эти данные являются по умолчанию чем-то неопределённым. Но, чтобы этот набор данных как-то «упаковать» в пригодной для работы оболочке, нужен «контейнер».

Переменная – это «контейнер» для хранения данных. Её значение можно менять. Переменная – это именно та самая «x» из математических примеров, где x=5+5.

Константа – тоже контейнер для данных, но её значение нельзя изменить после создания. Представим, что вам нужно объявить значение, и оно будет постоянным. Тогда и нужна константа.

В начальных примерах мы указывали именно константы, потому что подразумевали, что значение, указанное нами в коде, будет постоянным и неизменным.

Говоря о создании, поскольку фактически непосредственного «создания» не происходит, программирование использует термин «объявить». Переменную не создают, а объявляют.

Ключевые слова для объявления переменных

Ключевое словоОписаниеПример
letПеременная (значение можно менять)let age = 25
constКонстанта (значение нельзя менять)const PI = 3.14
varУстаревший вариант переменной varname = "Тимур"

Переменную можно объявить, и она уже будет в памяти. Потом ей можно изменить значение, допустим, x была равна 10, а потом можно её сделать равной 5. Константу, если мы указали как равной 10, уже значение не поменять. В коде это выглядит так:

// Переменная (можно менять)
let userName = "Оскар";
userName = "Хан"; // OK

// Константа (нельзя менять)
const birthYear = 1990;
birthYear = 2000; // Ошибка! TypeError: Assignment to constant variable.

Поэтому, если какое-то значение менять в процессе не потребуется, и оно всегда будет стабильным – лучше использовать константы, это займёт меньше ресурсов.

У вас может возникнуть вопрос - а почему var устаревшее ключевое слово для объявления переменной?

Мы помним, что такое область видимости переменной - как правило, она ограничивается блоком кода, где она была объявлена. Но область видимости переменных var не ограничивается блоком кода - она создаёт глобальную переменную. Допустим, если напишем if(true) { let name; } то name будет видна только внутри фигурных скобок блока if, при попытке доступа из других блоков name будет undefined. Но если мы аналогично сделаем var - if(true) { var name } то name станет видима!

Кроме этого, var допускает повторное объявление, в отличие от let - если вы напишете let name; let name; то на втором экземпляре «let name;» будет ошибка синтаксиса, потому что переменная name уже объявлена. В случае с var name; var name система ругаться не будет.

Ещё интересное отличие - var технически считается объявленным в самом начале работы функции. То есть, даже если вы поместите var в конец блока функции, системе будет «плевать», она начнёт исполнение с var, «переместив» в начало кода. И что самое сложное - такое объявление «перемещается» без своего значения.

Как использовать переменные?

Пример:

let name = "Тарзан";
let message = 'Привет, мир!';
let template = `Меня зовут ${name}`; // Шаблонная строка, для вызова надо указать ${имя переменной} и тогда будет работа с её значением

Здесь мы объявили три переменные:

  • name – её значение равно «Анна»;
  • message со значением «Привет мир!»;
  • template – «Меня зовут ${name}».

Шаблонная строка (template) будет выводить нам не просто текст, а динамически изменяемое значение, которое будет подставлять значение переменной, указанной через символ $ в скобках – в нашем случае, будет «Меня зовут Анна», так как выше мы указали, что name=«Анна».

Пример объекта:

const person = {
name: "Рэй",
age: 30,
isStudent: false
};

Здесь мы видим более сложный объект person, который включает в себя свойства, name, age, isStudent. Все эти три свойства друг от друга независимы, к примеру, isStudent может быть true. Следовательно, обратившись к person.name, person.age, person.isStudent – мы получим соответственно значения «Рэй», 30 и false. Так и работает объект.

Создание (объявление) переменной:

let age; // Объявили переменную (значение = undefined)

Объявить переменную можно через ключевое слово let или var. При объявлении значение можно не указывать. Логически это «пусть будет возраст».

Присваивание значения:

age = 25; // Теперь age = 25

Присваивание значение выполняется через символ равенства «=». Присваивание можно выполнить и при объявлении, но в нашем случае, это будет «Возраст равен 25».

Использование:

console.log(age); // 25

Поскольку ранее переменная age уже была объявлена – в памяти для неё выделено место, а после присвоения получено было и конкретное значение типа Number. Теперь можно просто указать имя переменной, чтобы использовать.

Правила именования переменных:

  • имена чувствительны к регистру (user, USER, User – разные переменные);
  • можно использовать буквы, цифры, _ и $;
  • нельзя начинать с цифры: 1user – ошибка;
  • нельзя использовать зарезервированные ключевые слова (let, function).

И разумеется, есть продвинутые операции с переменными. Как можно понять, это просто участок памяти, в который можно записать что угодно - к примеру, число, строку, объект или результат выполнения нескольких функций, всё зависит от сложности.

JS - динамически типизированный, что позволяет писать просто «пусть будет переменная», а система сама решит, что за тип, на основе значения — это значительно упрощает код. И допустим можно сделать так:

let array = [1,2]

Это массив, мы буквально сказали - пусть будет переменная по имени array, значением которой будет массив чисел из 1 и 2. И порой возникает задача, когда нужно распаковать такие массивы или объекты, раскидав их в несколько переменных. Это называется деструктирующее присваивание.

Мы просто объявляем, буквально в инверсии:

let [a, b] = array;

Так мы указываем, что a и b это соответствующие значения массива array, что позволит нам использовать соответствующие значения - a будет 1, b будет 2 (a - первый элемент массива, b второй):

console.log(a); // 1
console.log(b); // 2

Элементы массива можно пропускать, добавив «, ,»:

let [x, , z] = [10, 20, 30];

Можно указать …rest, чтобы выбрать массив оставшихся:

let [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5] → массив оставшихся

И можно устанавливать значения по умолчанию:

let [name = "Аноним", age = 18] = ["Алиса"];
console.log(name); // "Алиса"
console.log(age); // 18 → значение по умолчанию

Деструктуризация может быть применена и к объектам, но мы ещё их не изучили, поэтому вернёмся позже.